#include <iostream>
#include <vector>
using namespace std;

#define EIGHT

#if defined ONE

class Box
{
public:
    double GetVolume(void);
    void   SetLength(double Len);
    void   SetBreadth(double Bre);
    void   SetHeight(double Hei);
    Box    operator+(const Box& b);   // 这里的 重载运算符 被定义为了类的成员函数

private:   // 私有成员，在内外部是不可访问的，甚至是不可查看的，只有类和友元函数可以访问私有成员
    double Length;
    double Breadth;
    double Height;
};

double Box::GetVolume(void)
{
    return Length * Breadth * Height;
}

void Box::SetLength(double Len)
{
    Length = Len;
}

void Box::SetBreadth(double Bre)
{
    Breadth = Bre;
}

void Box::SetHeight(double Hei)
{
    Height = Hei;
}

// 传入的是对象的的引用
// 返回的是对象的值
Box Box::operator+(const Box& b)
{
    // 成员函数内部，也算是类内部
    Box box;

    cout << "调用了重载运算符" << endl;

    box.Length  = this->Length + b.Length;
    box.Breadth = this->Breadth + b.Breadth;
    box.Height  = this->Height + b.Height;
    return box;
}

int main(void)
{
    Box    box1;
    Box    box2;
    Box    box3;
    double Volume = 0.0;

    box1.SetLength(6.0);
    box1.SetBreadth(7.0);
    box1.SetHeight(5.0);

    box2.SetLength(12.0);
    box2.SetBreadth(13.0);
    box2.SetHeight(10.0);

    Volume = box1.GetVolume();
    cout << "Volume Of Box1 :" << Volume << endl;

    Volume = box2.GetVolume();
    cout << "Volume Of Box2 :" << Volume << endl;

    box3   = box1 + box2;   // 这里的加法运算符被重载了

    Volume = box3.GetVolume();
    cout << "Volume Of Box3 :" << Volume << endl;

    return 0;
}

#elif defined TWO

class Distance
{
private:
    int feet;     // 英尺
    int inches;   // 英寸
public:
    Distance(void);           // 构造函数没有返回值，哪怕是void 都没有  并且析构函数不但没有返回值，而且没有参数,void都没有
    Distance(int f, int i);   //
    void     DisplayDistance(void);
    Distance operator-();   // 这个重载运算符返回的数据类型是 Distance类
    bool     operator<(const Distance& d);
};

Distance::Distance(void)
{
    cout << "构造函数 Distance(void)" << endl;
    feet   = 0;
    inches = 0;
}

Distance::Distance(int f, int i)
{
    cout << "构造函数 Distance(int f, int i)" << endl;
    feet   = f;
    inches = i;
}

void Distance::DisplayDistance(void)
{
    cout << "F: " << feet << "I:" << inches << endl;
}

// 重载运算符 (-)
Distance Distance::operator-()
{
    cout << "重载运算符 (-)" << endl;

    this->feet   = -(this->feet);
    this->inches = -(this->inches);

    // 现在懂了，就是生成一个临时对象，然后将临时对象返回
    return Distance(this->feet, this->inches);   // 搞不懂这里是干啥的  ？？？？？？？？？？？？？？？有点神奇

    /**
     * 上面的写法和下面的写法效果是不同的
     */
    // Distance distance;

    // distance.feet   = -(this->feet);
    // distance.inches = -(this->inches);

    // return distance;
}

//
bool Distance::operator<(const Distance& d)
{
    if (this->feet < d.feet)
    {
        return true;
    }
    else if ((this->feet == d.feet) && (this->inches < d.inches))
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main(void)
{
    Distance D1(11, 10);
    Distance D2(5, 11);

    // -D1;
    // D1.DisplayDistance();
    // -D2;
    // D2.DisplayDistance();

    if (D1.operator<(D2))
    {
        cout << "D1 Is Less Than D2" << endl;
    }
    else
    {
        cout << "D1 Is Not Less Than D2" << endl;
    }

    return 0;
}

#elif defined THREE

class Distance
{
private:
    int feet;     // 英尺
    int inches;   // 英寸
public:
    Distance(void);                                                   // 构造函数没有返回值，哪怕是void 都没有  并且析构函数不但没有返回值，而且没有参数,void都没有
    Distance(int f, int i);                                           //
    friend ostream& operator<<(ostream& Output, const Distance& D);   // D里面不可被修改 就是引用的内容不可修改
    friend istream& operator>>(istream& Input, Distance& D);
};

Distance::Distance(void)
{
    cout << "构造函数 Distance(void)" << endl;
    feet   = 0;
    inches = 0;
}

Distance::Distance(int f, int i)
{
    cout << "构造函数 Distance(int f, int i)" << endl;
    feet   = f;
    inches = i;
}

/**
 * 因为友元函数不是，类的成员函数，所以 友元函数的定义 前面是不需要添加  Distance:: 的
 */
ostream& operator<<(ostream& Output, const Distance& D)
{
    cout << "operator<<";
    // TODO: insert return statement here
    Output << "F: " << D.feet << "I: " << D.inches;

    return Output;   // 相当于吃进去，又吐出来
}

istream& operator>>(istream& Input, Distance& D)
{
    cout << "operator>>";
    // TODO: insert return statement here
    Input >> D.feet >> D.inches;
    // 上面的语句相当于
    //   Input >> D.feet
    //   Input >> D.inches
    //   也就是说 先左，后右
    return Input;
}

int main(void)
{
    Distance D1(11, 10);
    Distance D2(5, 11);
    Distance D3;

    cout << "Enter The Value Of Object :" << endl;
    cin >> D3;                                  // 认准了 >> D3
    cout << "First Distance:" << D1 << endl;    // 认准了 << D1
    cout << "Second Distance:" << D2 << endl;   // 认准了 << D2
    cout << "Third Distance:" << D3 << endl;    // 认准了 << D3

    return 0;
}

#elif defined FOUR

class Time
{
private:
    int hours;
    int minutes;

public:
    Time(void);
    Time(int h, int m);
    void DisplayTime(void);
    // 重载前缀递增运算符
    Time operator++();
    // 重载后缀递增运算符
    Time operator++(int);   // why
};

Time::Time(void)
{
    cout << "Time(void)" << endl;
    hours   = 0;
    minutes = 0;
}

Time::Time(int h, int m)
{
    cout << "Time(int h, int m)" << endl;
    hours   = h;
    minutes = m;
}

void Time::DisplayTime(void)
{
    cout << "H: " << hours << " M: " << minutes << endl;
}

// 重载前缀递增运算符(相当于是改造++运算符)
Time Time::operator++()
{
    cout << "Time::operator++()" << endl;

    ++(this->minutes);
    if (this->minutes >= 60)
    {
        ++(this->hours);
        (this->minutes) -= 60;
    }
    return Time(this->hours, this->minutes);
}

// 重载后缀递增运算符
Time Time::operator++(int)
{
    cout << "Time::operator++(int)" << endl;

    Time T(this->hours, this->minutes);   // 相当于创建了一个临时对象变量

    ++(this->minutes);
    if (this->minutes >= 60)
    {
        ++(this->hours);
        (this->minutes) -= 60;
    }

    return T;   // 返回的是临时变量
}

int main(void)
{
    Time T1(11, 59);
    Time T2(10, 40);

    ++T1;
    T1.DisplayTime();
    ++T1;
    T1.DisplayTime();

    (T2++).DisplayTime();
    T2.DisplayTime();
    (T2++).DisplayTime();
    T2.DisplayTime();

    return 0;
}

#elif defined FIVE

class Distance
{
private:
    int feet;
    int inches;

public:
    Distance(void);           // 构造函数和析构函数没有返回值,连void都不会返回
    Distance(int f, int i);   // 构造函数
    void operator=(const Distance& D);
    void DisplayDistance(void);
};

Distance::Distance(void)
{
    feet   = 0;
    inches = 0;
}

Distance::Distance(int f, int i)
{
    feet   = f;
    inches = i;
}

// 这里的运算符重载为啥要这样写
void Distance::operator=(const Distance& D)
{
    this->feet   = D.feet;
    this->inches = D.inches;
}

void Distance::DisplayDistance(void)
{
    cout << "F: " << feet << " I:" << inches << endl;
}

int main(void)
{
    Distance D1(11, 10);
    Distance D2(5, 11);

    cout << "First Distance :";
    D1.DisplayDistance();
    cout << "Second Distance :";
    D2.DisplayDistance();
    // D1.operator=(D2);
    D1 = D2;   // 这两种写法都可以
    cout << "First Distance :";
    D1.DisplayDistance();

    return 0;
}

#elif defined SIX

class Distance
{
private:
    int feet;
    int inches;

public:
    Distance(void);                             // 构造函数和析构函数没有返回值,连void都不会返回
    Distance(int f, int i);                     // 构造函数
    Distance operator()(int a, int b, int c);   // 显然，这里面要临时申请一个对象
    void     DisplayDistance(void);
};

Distance::Distance(void)
{
    feet   = 0;
    inches = 0;
}

Distance::Distance(int f, int i)
{
    feet   = f;
    inches = i;
}

// 这里的运算符重载为啥要这样写   函数调用重载运算符
Distance Distance::operator()(int a, int b, int c)
{
    return Distance(a + c + 10, b + c + 100);
}

void Distance::DisplayDistance(void)
{
    cout << "F: " << feet << " I:" << inches << endl;
}

int main(void)
{
    Distance D1(11, 10);
    Distance D2;

    cout << "First Distance :";
    D1.DisplayDistance();
    D2 = D1(10, 10, 10);
    cout << "Second Distance :";
    D2.DisplayDistance();

    return 0;
}

#elif defined SEVEN

const int SIZE = 10;

/**
 * 下标操作符[] 通常用于访问数组元素
 */
class SafeArray
{
private:
    int Array[SIZE];

public:
    SafeArray(void);
    int& operator[](int i);
};

SafeArray::SafeArray(void)
{
    register int i;
    for (i = 0; i < SIZE; i++)
    {
        Array[i] = i;   // 0 ~ SIZE-1
    }
}

int& SafeArray::operator[](int i)
{
    if (i >= SIZE)
    {
        cout << "索引超过最大值" << endl;
        return Array[0];
    }
    return Array[i];
}

int main(void)
{
    SafeArray A;

    cout << "A[2]的值为 :" << A.operator[](2) << endl;   // 看来这种写法也OK
    cout << "A[5]的值为 :" << A[5] << endl;
    cout << "A[12]的值为 :" << A[12] << endl;

    return 0;
}

#elif defined EIGHT

class Obj
{
private:
    static int i;
    static int j;

public:   // 关于 const成员函数相关知识，见StorageClass.cpp
    void f() const;
    void g() const;
};

int Obj::i = 10;   // 静态成员变量定义
int Obj::j = 12;

void Obj::f() const
{
    cout << i++ << endl;   // 先输出 i的值，然后 i++
}

void Obj::g() const
{
    cout << j++ << endl;
}

////////////////////////////////////////////

class ObjContainer
{
private:
    vector<Obj*> a;   // 创建一个空的Obj对象指针的向量(容器)
public:
    void Add(Obj* obj);
    friend class SmartPointer;   // 这个友元类不是这个类的成员  关于 友元的知识参见 ClassAndObject.cpp
};

void ObjContainer::Add(Obj* obj)
{
    a.push_back(obj);
}

////////////////////////////////////////////

// 这个友元类可以访问 上面 ObjContainer类里面的所有成员
class SmartPointer
{
private:
    ObjContainer oc;
    uint32_t     Index;   // 这两个只能在类里面使用

public:
    SmartPointer(ObjContainer& objc);   // 好像拷贝构造函数   构造函数和析构函数 没有返回值(void都没有)
    // 下面都是重载运算符
    bool operator++();      // 前缀版本
    bool operator++(int);   // 后缀版本
    Obj* operator->() const;
};

SmartPointer::SmartPointer(ObjContainer& objc)
{
    oc    = objc;
    Index = 0;
}

// 这个前缀++是干啥的
bool SmartPointer::operator++()
{
    if (Index >= (oc.a.size() - 1))
    {   // Index指向最后一个，或者往后都不行 (因为最后一个 Index在上一轮已经被用过了)
        return false;
    }
    if (oc.a[++Index] == 0)   // 这里的++Index有可能刚好 指向最后一个
    {
        return false;
    }
    return true;
}

// 这个后缀++是干啥的
bool SmartPointer::operator++(int)   // 返回值表示列表结束
{
    return operator++();
}

Obj* SmartPointer::operator->() const
{
    if (!(oc.a[Index]))
    {
        cout << "Zero Value";
        return (Obj*)0;
    }
    return oc.a[Index];
}
////////////////////////////////////////////

int main(void)
{
    const int    sz = 10;
    Obj          o[sz];   // 对象数组
    ObjContainer oc;

    for (int i = 0; i < sz; i++)
    {
        oc.Add(o + i);
    }
    SmartPointer sp(oc);   // 创建一个迭代器
    do
    {
        sp->f();   // 因为 f和g是public对的
        sp->g();
    } while (sp++);
    return 0;
}

#elif defined NINE

#endif

/**
 *  override 可以理解为推翻覆盖的意思
 *
 * C++里面函数的重载
 *     在同一个作用域内，可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数,类型或者顺序)必须不同，不能仅通过返回类型的不同来重载函数
 *
 * C++里面的运算符重载 (可以理解为重新定义运算符)
 *     例如 Box operator+(const Box&);  这里表示声明加法运算符，用于把两个Box对象相加，返回最终的Box对象。
 *     大多数的重载运算符可被定义为普通的非成员函数或者被定义为类成员函数。如果我们定义上面的函数为类的非成员
 *     函数，那么我们需要为每次操作传递两个参数,如下:  Box operator+(const Box& ,const Box&);
 *
 *     C++中运算符重载在类内(成员函数  就算声明在类内部，实现在类外部也算)  和 类外(全局函数/友元函数)
 *       类内部实现,直接访问私有成员，无需友元声明  ;隐含this指针作为第一个操作数，二元运算符只需显式传递右操作数 调用形式为obj.operator+(rhs)，或直接使用运算符obj + rhs
 *
 *       内外部实现，支持左操作数为非类类型(如 int+obj)
 *       避免this指针带来的隐式绑定(言下之意就是 无法直接访问私有成员变量)
 *       需声明为友元函数以访问私有成员，需显式传递左右两个操作数
 *       调用形式为operator+(lhs, rhs)，或直接lhs + rhs
 *
 *     C++里面不可重载的运算符,如下
 *          .成员访问运算符
 *          -> 成员指针运算符    这里得注意它和 类成员访问运算符->的区别
 *          :: 域运算符
 *          sizeof 长度运算符
 *          ? : 条件运算符
 *          # 预处理符号
 *
 *     C++函数重载运算符() 可以被重载用于类的对象,当重载()时,您不是创造了一种新的调用函数的方式，相反的，这是创建了一个可以传递
 *     任意数目参数的运算符函数
 *
 *     类成员访问运算符(->)可以被重载，但它较为麻烦，他被定义用于为一个类赋予"指针行为"。运算符->必须是一个成员函数。
 *     如果使用了->运算符，返回类型必须是指针或者是类的对象
 *     运算符->通常与指针引用运算符* 相结合使用,用于实现智能指针功能。这些指针是行为与正常指针相似的对象，唯一不同的是，当您
 *     通过指针访问对象时，它会执行其它的任务。比如，当指针销毁时,或者当指针指向另一个对象时，会自动删除对象
 *
 *     间接引用运算符->可以被定义为一个一元后缀运算符。也就是说，给出一个类
 *      class Ptr
 *      {
 *          X * operator->();
 *      };
 *      类Ptr的对象可用于访问类X的成员,使用方式与指针的用法十分类似，比如:
 *      void f(Ptr p)
 *      {
 *          p->m=10;   // (p.operator->())->m=10;
 *      }
 *
 *      感觉C++还要系统的学习一下
 */
